package pprof

import (
	"epg/stats"
	"epg/utils"
	"runtime"
	"time"
)

var (
	collectDelay = 30 * time.Second
)

const (
	tag             = "pprof"
	tagNumGoroutine = tag + ".NumGoroutine"
	tagNumCgoCall   = tag + ".NumCgoCall"
	tagNumGC        = tag + ".NumGC"
	tagAlloc        = tag + ".Alloc"
	tagTotalAlloc   = tag + ".TotalAlloc"
	tagSys          = tag + ".Sys"
	tagLookups      = tag + ".Lookups"
	tagMallocs      = tag + ".Mallocs"
	tagFrees        = tag + ".Frees"
	tagHeapAlloc    = tag + ".HeapAlloc"
	tagHeapSys      = tag + ".HeapSys"
	tagHeapIdle     = tag + ".HeapIdle"
	tagHeapInuse    = tag + ".HeapInuse"
	tagHeapReleased = tag + ".HeapReleased"
	tagHeapObjects  = tag + ".HeapObjects"
	tagStackInuse   = tag + ".StackInuse"
	tagStackSys     = tag + ".StackSys"
	tagMSpanInuse   = tag + ".MSpanInuse"
	tagMSpanSys     = tag + ".MSpanSys"
	tagMCacheInuse  = tag + ".MCacheInuse"
	tagMCacheSys    = tag + ".MCacheSys"
	tagBuckHashSys  = tag + ".BuckHashSys"
	tagGCSys        = tag + ".GCSys"
	tagOtherSys     = tag + ".OtherSys"

	tagPauseTotal = "gcpause.PauseTotal"
	tagLastPause  = "gcpause.LastPause"
)

//Start start the pprof
func Start() {
	stats.NewStats()
	go pprofTask()
}

// profiling task
func pprofTask() {
	defer utils.PrintPanicStack()
	for {
		<-time.After(collectDelay)
		collect()
	}
}

// collect & publish to statsd
func collect() {
	_statter := stats.Stater.Client
	// collect
	memstats := &runtime.MemStats{}
	runtime.ReadMemStats(memstats)

	_statter.Gauge(tagNumGoroutine, runtime.NumGoroutine())
	_statter.Gauge(tagNumCgoCall, runtime.NumCgoCall())
	if memstats.NumGC > 0 {
		_statter.Timing(tagPauseTotal, memstats.PauseTotalNs)
		_statter.Timing(tagLastPause, memstats.PauseNs[(memstats.NumGC+255)%256])
		_statter.Gauge(tagNumGC, memstats.NumGC)
		_statter.Gauge(tagAlloc, memstats.Alloc)
		_statter.Gauge(tagTotalAlloc, memstats.TotalAlloc)
		_statter.Gauge(tagSys, memstats.Sys)
		_statter.Gauge(tagLookups, memstats.Lookups)
		_statter.Gauge(tagMallocs, memstats.Mallocs)
		_statter.Gauge(tagFrees, memstats.Frees)
		_statter.Gauge(tagHeapAlloc, memstats.HeapAlloc)
		_statter.Gauge(tagHeapSys, memstats.HeapSys)
		_statter.Gauge(tagHeapIdle, memstats.HeapIdle)
		_statter.Gauge(tagHeapInuse, memstats.HeapInuse)
		_statter.Gauge(tagHeapReleased, memstats.HeapReleased)
		_statter.Gauge(tagHeapObjects, memstats.HeapObjects)
		_statter.Gauge(tagStackInuse, memstats.StackInuse)
		_statter.Gauge(tagStackSys, memstats.StackSys)
		_statter.Gauge(tagMSpanInuse, memstats.MSpanInuse)
		_statter.Gauge(tagMSpanSys, memstats.MSpanSys)
		_statter.Gauge(tagMCacheInuse, memstats.MCacheInuse)
		_statter.Gauge(tagMCacheSys, memstats.MCacheSys)
		_statter.Gauge(tagBuckHashSys, memstats.BuckHashSys)
		_statter.Gauge(tagGCSys, memstats.GCSys)
		_statter.Gauge(tagOtherSys, memstats.OtherSys)
	}
}
